package com.aizhixin.lab.course.course.service;

import com.aizhixin.lab.account.dto.AccountDTO;
import com.aizhixin.lab.common.core.ApiReturnConstants;
import com.aizhixin.lab.common.core.DataValidity;
import com.aizhixin.lab.common.core.PageData;
import com.aizhixin.lab.common.core.PageUtil;
import com.aizhixin.lab.common.domain.PageDomain;
import com.aizhixin.lab.common.utils.PageJdbcUtil;
import com.aizhixin.lab.course.classes.dto.CourseClassDTO;
import com.aizhixin.lab.course.classes.service.CourseClassService;
import com.aizhixin.lab.course.course.domain.CourseBaseDomain;
import com.aizhixin.lab.course.course.domain.CourseDomain;
import com.aizhixin.lab.course.course.domain.CourseFileDomain;
import com.aizhixin.lab.course.course.domain.CourseProfDomain;
import com.aizhixin.lab.course.course.dto.CourseDTO;
import com.aizhixin.lab.course.course.dto.CourseFileCountDTO;
import com.aizhixin.lab.course.course.dto.CourseFileDTO;
import com.aizhixin.lab.course.course.dto.CourseProfDTO;
import com.aizhixin.lab.course.course.entity.Course;
import com.aizhixin.lab.course.course.entity.CourseFile;
import com.aizhixin.lab.course.course.entity.CourseProf;
import com.aizhixin.lab.course.course.repository.*;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;

@Slf4j
@Service
@Transactional
public class TeacherCourseService {
    @Autowired
    private CourseRepository courseRepository;
    @Autowired
    private CourseFileRepository courseFileRepository;
    @Autowired
    private CourseProfRepository courseProfRepository;
    @Autowired
    private CourseChapterRepository courseChapterRepository;
    @Autowired
    private CourseChapterFileRepository courseChapterFileRepository;
    @Autowired
    private CourseAssistRepository courseAssistRepository;
    @Autowired
    private CourseClassService courseClassService;
    @Autowired
    private PageJdbcUtil pageJdbcUtil;
    @Autowired
    private CourseLikeRepository courseLikeRepository;
    @Autowired
    private TeacherLikeRepository teacherLikeRepository;

    public PageData<CourseBaseDomain> getList(Long userId, String name, Integer type, Integer pageNumber, Integer pageSize) {
        Pageable pageable = PageUtil.createRequestAndSortType(pageNumber, pageSize, "desc", "createdDate");
        Page<Course> page;
        if (type != null && type > 0) {
            if (StringUtils.isEmpty(name)) {
                page = courseRepository.findByTypeAndCreatedByAndDeleteFlag(pageable, type, userId, DataValidity.VALID.getState());
            } else {
                name = "%" + name + "%";
                page = courseRepository.findByTypeAndCreatedByAndDeleteFlagAndNameLikeIgnoreCase(pageable, type, userId, DataValidity.VALID.getState(), name);
            }
        } else {
            if (StringUtils.isEmpty(name)) {
                page = courseRepository.findByCreatedByAndDeleteFlag(pageable, userId, DataValidity.VALID.getState());
            } else {
                name = "%" + name + "%";
                page = courseRepository.findByCreatedByAndDeleteFlagAndNameLikeIgnoreCase(pageable, userId, DataValidity.VALID.getState(), name);
            }
        }
        PageDomain pageDomain = new PageDomain();
        pageDomain.setPageSize(page.getSize());
        pageDomain.setPageNumber(page.getNumber());
        pageDomain.setTotalElements(page.getTotalElements());
        pageDomain.setTotalPages(page.getTotalPages());

        PageData<CourseBaseDomain> pageData = new PageData<>();
        pageData.setData(getCourseDomains(page.getContent(), false));
        pageData.setPage(pageDomain);
        return pageData;
    }

    public PageData<CourseBaseDomain> getPublishedList(Long userId, Boolean isArchive, String name, Integer type, Boolean isPublish, Integer pageNumber, Integer pageSize, boolean isCountFile) {
        Pageable pageable = PageUtil.createRequestAndSortType(pageNumber, pageSize, "desc", "createdDate");
        Page<Course> page;
        if (type != null && type > 0) {
            if (StringUtils.isEmpty(name)) {
                page = courseRepository.findByIsPublishAndIsArchiveAndTypeAndCreatedByAndDeleteFlag(pageable, isPublish, isArchive, type, userId, DataValidity.VALID.getState());
            } else {
                name = "%" + name + "%";
                page = courseRepository.findByIsPublishAndIsArchiveAndTypeAndCreatedByAndDeleteFlagAndNameLikeIgnoreCase(pageable, isPublish, isArchive, type, userId, DataValidity.VALID.getState(), name);
            }
        } else {
            if (StringUtils.isEmpty(name)) {
                page = courseRepository.findByIsPublishAndIsArchiveAndCreatedByAndDeleteFlag(pageable, isPublish, isArchive, userId, DataValidity.VALID.getState());
            } else {
                name = "%" + name + "%";
                page = courseRepository.findByIsPublishAndIsArchiveAndCreatedByAndDeleteFlagAndNameLikeIgnoreCase(pageable, isPublish, isArchive, userId, DataValidity.VALID.getState(), name);
            }
        }
        for (Course item : page.getContent()) {
            item.setCountChapter(item.getViewCountChapter());
            item.setCountSection(item.getViewCountSection());
        }
        PageDomain pageDomain = new PageDomain();
        pageDomain.setPageSize(page.getSize());
        pageDomain.setPageNumber(page.getNumber());
        pageDomain.setTotalElements(page.getTotalElements());
        pageDomain.setTotalPages(page.getTotalPages());

        PageData<CourseBaseDomain> pageData = new PageData<>();
        pageData.setData(getCourseDomains(page.getContent(), isCountFile));
        pageData.setPage(pageDomain);
        return pageData;
    }

    RowMapper<CourseDomain> rm1 = new RowMapper<CourseDomain>() {

        @Override
        public CourseDomain mapRow(ResultSet rs, int rowNum)
                throws SQLException {
            // TODO Auto-generated method stub
            CourseDomain domain = new CourseDomain();
            domain.setId(rs.getString("course_id"));
            domain.setCountVm(rs.getInt("vm_count"));
            return domain;
        }
    };

    public List<CourseDomain> getCourseVmCount(String courseIds) {
        String sql = "select cc.course_id,COUNT(*) as vm_count from `c_course_chapter` cc where cc.course_id in (" + courseIds + ") and cc.vm_num > 0 and cc.delete_flag = 0 GROUP BY cc.course_id";
        return pageJdbcUtil.getInfo(sql, rm1);
    }


    RowMapper<CourseFileCountDTO> rm2 = new RowMapper<CourseFileCountDTO>() {

        @Override
        public CourseFileCountDTO mapRow(ResultSet rs, int rowNum)
                throws SQLException {
            // TODO Auto-generated method stub
            CourseFileCountDTO domain = new CourseFileCountDTO();
            domain.setType(rs.getInt("type"));
            domain.setCountNum(rs.getInt("count_num"));
            return domain;
        }
    };

    public List<CourseFileCountDTO> getCourseFileCount(String courseId) {
        String sql = "select type,count(*) as count_num from `c_course_chapter_file` ccf where ccf.chapter_id in(select cc.id from `c_course_chapter` cc where cc.course_id = '" + courseId + "') and ccf.type in(10,20,30,40,50) and ccf.delete_flag = 0 GROUP BY ccf.type;";
        return pageJdbcUtil.getInfo(sql, rm2);
    }


    private List<CourseBaseDomain> getCourseDomains(List<Course> list, boolean isCountFile) {
        List<CourseBaseDomain> result = new ArrayList();
        if (!list.isEmpty()) {
            String courseIds = "";
            for (Course item : list) {
                if (!StringUtils.isEmpty(courseIds)) {
                    courseIds += ",";
                }
                courseIds += "'" + item.getId() + "'";
                CourseBaseDomain d = new CourseBaseDomain();
                BeanUtils.copyProperties(item, d);

                if (isCountFile) {
                    List<CourseFileCountDTO> fileCountList = getCourseFileCount(item.getId());
                    d.setFileCountList(fileCountList);
                }
                result.add(d);
            }

            List<CourseDomain> countList = getCourseVmCount(courseIds);
            if (countList.isEmpty()) {
                log.debug("countVm list isEmpty!!!!!!!");
            } else {
                log.debug("countVm list =" + countList.size());
            }
            HashMap<String, Integer> countMap = new HashMap<String, Integer>();
            for (CourseDomain domain : countList) {
                countMap.put(domain.getId(), domain.getCountVm());
            }


            List<CourseClassDTO> classDTOS = courseClassService.findCourseClassList(courseIds);
            if (classDTOS != null && !classDTOS.isEmpty()) {
                for (CourseBaseDomain item : result) {
                    String classNames = "";
                    Integer countClass = 0;
                    Integer countStudent = 0;

                    if (null != countMap.get(item.getId())) {
                        item.setCountVm(countMap.get(item.getId()));
                    }

                    for (CourseClassDTO cc : classDTOS) {
                        if (cc.getCourseId().equals(item.getId())) {
                            if (!StringUtils.isEmpty(classNames)) {
                                classNames += " ";
                            }
                            classNames += cc.getClassName();
                            countClass++;
                            countStudent += cc.getStuNum();
                        }
                    }
                    item.setClassNames(classNames);
                    item.setCountClass(countClass);
                    item.setCountStudent(countStudent);
                }
            } else {
                for (CourseBaseDomain item : result) {
                    if (null != countMap.get(item.getId())) {
                        item.setCountVm(countMap.get(item.getId()));
                    }
                }
            }
        }
        return result;
    }

    public List<CourseBaseDomain> getRecentlyList(Long userId) {
        Pageable pageable = PageUtil.createRequestAndSortType(1, 2, "desc", "lastModifiedDate");
        Page<Course> page = courseRepository.findByIsPublishAndIsArchiveAndCreatedByAndDeleteFlag(pageable, true, false, userId, DataValidity.VALID.getState());
        return getCourseDomains(page.getContent(), false);
    }

    public CourseDomain getCourse(AccountDTO account, String courseId, boolean hasHide) {
        CourseDomain domain = new CourseDomain();
        Course course = courseRepository.findByIdAndDeleteFlag(courseId, DataValidity.VALID.getState());
        if (course != null) {
            BeanUtils.copyProperties(course, domain);
            if (!hasHide) {
                domain.setCountChapter(course.getViewCountChapter());
                String sql = "SELECT COUNT(DISTINCT c.parent_id) FROM c_course_chapter c WHERE c.course_id='" + courseId + "' AND c.delete_flag=0 AND c.parent_id IS NOT NULL AND c.is_hide=0";
                Integer countInt1 = pageJdbcUtil.getCountInt(sql);
                domain.setCountSection(domain.getCountSection() + domain.getCountChapter() - countInt1);
//                domain.setCountSection(course.getViewCountSection());
            }
            domain.setTeacherName(account.getName());
            domain.setTeacherAvatar(account.getAvatar());
            List<CourseFile> files = courseFileRepository.findByCourseIdAndDeleteFlag(courseId, DataValidity.VALID.getState());
            if (files != null && !files.isEmpty()) {
                List<CourseFileDomain> list = new ArrayList<>();
                for (CourseFile item : files) {
                    if (!hasHide) {
                        if (item.getIsHide() == null || !item.getIsHide()) {
                            CourseFileDomain d = new CourseFileDomain();
                            BeanUtils.copyProperties(item, d);
                            list.add(d);
                        }
                    } else {
                        CourseFileDomain d = new CourseFileDomain();
                        BeanUtils.copyProperties(item, d);
                        list.add(d);
                    }
                }
                domain.setFileList(list);
            }
            List<CourseProf> profs = courseProfRepository.findByCourseIdAndDeleteFlag(courseId, DataValidity.VALID.getState());
            if (profs != null && !profs.isEmpty()) {
                List<CourseProfDomain> list = new ArrayList<>();
                for (CourseProf item : profs) {
                    CourseProfDomain d = new CourseProfDomain();
                    BeanUtils.copyProperties(item, d);
                    list.add(d);
                }
                domain.setProfList(list);
            }
            domain.setCourseLikeNum(courseLikeRepository.countByCourseId(domain.getId()));
            domain.setTeacherLikeNum(teacherLikeRepository.countByTeacherIdAndCourseId(course.getCreatedBy(), course.getId()));
        }

        return domain;
    }

    public Map<String, Object> recently(String courseId) {
        Map<String, Object> result = new HashMap<>();
        Course course = courseRepository.findByIdAndDeleteFlag(courseId, DataValidity.VALID.getState());
        if (course != null) {
            course.setLastModifiedDate(new Date());
            courseRepository.save(course);
            result.put(ApiReturnConstants.SUCCESS, true);
        } else {
            result.put(ApiReturnConstants.SUCCESS, false);
            result.put(ApiReturnConstants.ERROR, "没有课程信息");
        }
        return result;
    }

    public Map<String, Object> archive(String courseId) {
        Map<String, Object> result = new HashMap<>();
        Course course = courseRepository.findByIdAndDeleteFlag(courseId, DataValidity.VALID.getState());
        if (course != null) {
            if (course.getIsPublish()) {
                course.setIsArchive(true);
                courseRepository.save(course);
                result.put(ApiReturnConstants.SUCCESS, true);
            } else {
                result.put(ApiReturnConstants.SUCCESS, false);
                result.put(ApiReturnConstants.ERROR, "课程无法归档");
            }
        } else {
            result.put(ApiReturnConstants.SUCCESS, false);
            result.put(ApiReturnConstants.ERROR, "没有课程信息");
        }
        return result;
    }

    public Map<String, Object> save(CourseDTO dto, Boolean isOpenSync) {
        Map<String, Object> result = new HashMap<>();
        Course course = null;
        if (!StringUtils.isEmpty(dto.getId())) {
            course = courseRepository.findByIdAndDeleteFlag(dto.getId(), DataValidity.VALID.getState());
        }
        if (course == null) {
            result.put(ApiReturnConstants.SUCCESS, false);
            result.put(ApiReturnConstants.ERROR, "没有课程信息");
        } else {
            courseFileRepository.deleteByCourseId(dto.getId());
            courseProfRepository.deleteByCourseId(dto.getId());
            BeanUtils.copyProperties(dto, course);
            course = courseRepository.save(course);
            if (dto.getFileList() != null && !dto.getFileList().isEmpty()) {
                List<CourseFile> list = new ArrayList<>();
                for (CourseFileDTO item : dto.getFileList()) {
                    CourseFile file = new CourseFile();
                    file.setCourseId(course.getId());
                    file.setName(item.getName());
                    file.setFileUrl(item.getFileUrl());
                    file.setFileKey(item.getFileKey());
                    file.setIsHide(item.getIsHide());
                    list.add(file);
                }
                courseFileRepository.save(list);
            }
            if (dto.getProfList() != null && !dto.getProfList().isEmpty()) {
                List<CourseProf> list = new ArrayList<>();
                for (CourseProfDTO item : dto.getProfList()) {
                    CourseProf prof = new CourseProf();
                    prof.setCourseId(course.getId());
                    prof.setProfId(item.getProfId());
                    prof.setProfName(item.getProfName());
                    list.add(prof);
                }
                courseProfRepository.save(list);
            }
            result.put(ApiReturnConstants.SUCCESS, true);
            result.put("courseId", course.getId());
            if (isOpenSync) {
                if (course.getIsPublish()){
                    if (course.getParentId()!=null) {
                        List<Course> courseList = courseRepository.findByParentIdAndDeleteFlag(course.getParentId(), DataValidity.VALID.getState());
                        courseList.forEach(item -> {
                            CourseDTO courseDTO = new CourseDTO();
                            BeanUtils.copyProperties(dto, courseDTO);
                            courseDTO.setId(item.getId());
                            save(courseDTO, false);
                        });
                        dto.setId(course.getId());
                        save(dto, false);
                    }
                }else {
                    List<Course> courseList = courseRepository.findByParentIdAndDeleteFlag(course.getId(), DataValidity.VALID.getState());
                    courseList.forEach(item -> {
                        CourseDTO courseDTO = new CourseDTO();
                        BeanUtils.copyProperties(dto, courseDTO);
                        courseDTO.setId(item.getId());
                        save(courseDTO, false);
                    });
                }
            }
        }
        return result;
    }

    public Map<String, Object> delete(String courseId) {
        Map<String, Object> result = new HashMap<>();
        Course course = courseRepository.findByIdAndDeleteFlag(courseId, DataValidity.VALID.getState());
        if (course != null) {
            course.setDeleteFlag(DataValidity.INVALID.getState());
            course.setLastModifiedDate(new Date());
            courseRepository.save(course);
            result.put(ApiReturnConstants.SUCCESS, true);
        } else {
            result.put(ApiReturnConstants.SUCCESS, false);
            result.put(ApiReturnConstants.ERROR, "没有课程信息");
        }
        return result;
    }

    public PageData<CourseBaseDomain> getTrashList(Long userId, String name, Integer pageNumber, Integer pageSize) {
        Pageable pageable = PageUtil.createRequestAndSortType(pageNumber, pageSize, "desc", "createdDate");
        Page<Course> page;
        if (StringUtils.isEmpty(name)) {
            page = courseRepository.findByCreatedByAndDeleteFlag(pageable, userId, DataValidity.INVALID.getState());
        } else {
            page = courseRepository.findByCreatedByAndDeleteFlagAndNameLikeIgnoreCase(pageable, userId, DataValidity.INVALID.getState(), name);
        }
        for (Course item : page.getContent()) {
            item.setCountChapter(item.getViewCountChapter());
            item.setCountSection(item.getViewCountSection());
        }
        PageDomain pageDomain = new PageDomain();
        pageDomain.setPageSize(page.getSize());
        pageDomain.setPageNumber(page.getNumber());
        pageDomain.setTotalElements(page.getTotalElements());
        pageDomain.setTotalPages(page.getTotalPages());

        PageData<CourseBaseDomain> pageData = new PageData<>();
        pageData.setData(getCourseDomains(page.getContent(), false));
        pageData.setPage(pageDomain);
        return pageData;
    }

    public Map<String, Object> putBack(String courseId) {
        Map<String, Object> result = new HashMap<>();
        Course course = courseRepository.findByIdAndDeleteFlag(courseId, DataValidity.INVALID.getState());
        if (course != null) {
            course.setDeleteFlag(DataValidity.VALID.getState());
            courseRepository.save(course);
            result.put(ApiReturnConstants.SUCCESS, true);
        } else {
            result.put(ApiReturnConstants.SUCCESS, false);
            result.put(ApiReturnConstants.ERROR, "没有课程信息");
        }
        return result;
    }

    public Map<String, Object> emptyTrash(String courseId) {
        Map<String, Object> result = new HashMap<>();
        Course course = courseRepository.findByIdAndDeleteFlag(courseId, DataValidity.INVALID.getState());
        if (course != null) {
            course.setDeleteFlag(2);
            courseRepository.save(course);
            result.put(ApiReturnConstants.SUCCESS, true);
        } else {
            result.put(ApiReturnConstants.SUCCESS, false);
            result.put(ApiReturnConstants.ERROR, "没有课程信息");
        }
        return result;
    }

}
